package gulimall.controller;

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import gulimall.constant.AuthServerConstant;
import gulimall.feign.MemberFeignService;
import gulimall.pojo.vo.GiteeUser;
import gulimall.pojo.vo.SocialUser;
import gulimall.utils.HttpUtils;
import gulimall.utils.R;
import gulimall.vo.MemberRespVO;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpResponse;
import org.apache.http.util.EntityUtils;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.util.HashMap;
import java.util.Map;

/**
 * OAuth2.0第三方授权登录
 *
 * @author HLF
 * @date 2022/8/2 19:19
 */
@Slf4j
@Controller
@RequiredArgsConstructor
public class OAuth2Controller {

    private final MemberFeignService memberFeignService;

    /**
     * 社交登录-gitee登录
     * 1.根据code换取access token
     * 2.远程调用会员服务保存会员信息和access token
     */
    @GetMapping("/oauth2.0/gitee/success")
    public String gitee(@RequestParam("code") String code,
                        RedirectAttributes redirectAttributes,
                        HttpServletResponse servletResponse,
                        HttpSession session) throws Exception {
        Map<String, String> header = new HashMap<>();
        Map<String, String> query = new HashMap<>();

        Map<String, String> body = new HashMap<>();

        body.put("client_id", "0b19efab94711b14f3e4f698a5bd7c2cff32214d1fbebeda1777cbe490cca5d8");
        body.put("client_secret", "a34056adeb0b27fa333310239ac37bde94b3f74b412ffd6852d31d6d5c542c84");
        body.put("grant_type", "authorization_code");
        body.put("redirect_uri", "http://auth.firstgulimall.com/oauth2.0/gitee/success");
        body.put("code", code);
        //1、根据code换取accessToken；
        //应用服务器 或 Webview 使用 access_token API 向 码云认证服务器发送post请求传入 用户授权码 以及 回调地址（ POST请求 ）
        //注：请求过程建议将 client_secret 放在 Body 中传值，以保证数据安全。
        //https://gitee.com/oauth/token?grant_type=authorization_code&code={code}&client_id={client_id}&redirect_uri={redirect_uri}&client_secret={client_secret}
        HttpResponse response = HttpUtils.doPost("https://gitee.com", "/oauth/token", "post", header, query, body);

        //2、如果access token正确(登陆成功)，返回商城首页
        ObjectMapper mapper = new ObjectMapper();
        if (response.getStatusLine().getStatusCode() == 200) {
            String jsonString = EntityUtils.toString(response.getEntity());
            //反序列化为SocialUser
            SocialUser socialUser = mapper.readValue(jsonString, new TypeReference<SocialUser>() {
            });

            Map<String, String> map1 = new HashMap<>();
            map1.put("access_token", socialUser.getAccess_token());
            HttpResponse response1 = HttpUtils.doGet("https://gitee.com", "/api/v5/user", "get", header, map1);
            String json1 = EntityUtils.toString(response1.getEntity());
            GiteeUser giteeUser = mapper.readValue(json1, GiteeUser.class);
            socialUser.setUId(giteeUser.getId());//给socialUser设置一个唯一的id，以便于区别是否是第一次登录的用户


            //知道当前是哪个社交用户
            //1）、当前用户如果是第一次进网站(根据uId判断)，自动注册进来(为当前社交用户生成一个会员信息账号，以后这个社交账号就对应指定的会员)
            //登录或者注册这个社交用户
            //远程调用gulimall-member服务的会员gitee社交登录接口
            R r = memberFeignService.oauth2Login(socialUser);
            if (r.getCode() == 0) {

                //这个会员对象主要作用是响应给前端
                MemberRespVO memberRespVO = r.get("memberEntity", new TypeReference<MemberRespVO>() {
                });
                log.info("会员登录成功：{}", memberRespVO);
                /**
                 * 第一次使用Session，让浏览器保存一个cookie-->>JSESSIONID
                 * 以后浏览器访问系统的网站就会带上这个cookie
                 * 那么子域之间：firstgulimall.com, auth.firstgulimall.com, order.gulimall.com 就可以共享JSESSIONID对应Session
                 * 保存这个cookie-->>JSESSIONID的时候，指定域名为父域名(firstgulimall.com)即使是子域的JSESSIONID，SpringSession也可以扩大作用域
                 */
                //以下操作由SpringSession完成，实现分布式Session共享
                //session.setAttribute("member", memberRespVO);
                //Cookie jsessionid = new Cookie("JSESSIONID", "123");//JSESSIONID由tomcat生成
                //jsessionid.setDomain("firstgulimall.com");
                //servletResponse.addCookie(jsessionid);

                session.setAttribute(AuthServerConstant.LOGIN_USER, memberRespVO);


                return "redirect:http://firstgulimall.com";
            } else {
                redirectAttributes.addFlashAttribute("msg", "登录失败");
                return "redirect:http://auth/firstgulimall.com/login.html";
            }

        } else {
            redirectAttributes.addFlashAttribute("msg", "登录失败");
            return "redirect:http://auth.firstgulimall.com";
        }
    }
}
